import api from '@/store/api';
import i18n from '@/i18n';
const { t } = i18n.global as any;

export const useFirmwareStore = defineStore('firmwareStore', () => {
  const bmcFirmware = ref([] as any[]);
  const hostFirmware = ref([] as any[]);
  const cpldFirmware = ref([] as any[]);
  const hostPbfActiveFirmwareId = ref(null);
  const bmcActiveFirmwareId = ref(null);
  const hostActiveFirmwareId = ref(null);
  const cpldActiveFirmwareId = ref(null);
  const applyTime = ref(null);
  const tftpAvailable = ref(false);
  const updateProgress = ref(0);

  const isTftpUploadAvailable = computed(() => tftpAvailable.value);
  const isSingleFileUploadEnabled = computed(
    () => hostFirmware.value.length === 0,
  );
  const activeBmcFirmware = computed(() =>
    bmcFirmware.value.find(
      (firmware: { version: string }) =>
        firmware.version === bmcActiveFirmwareId.value,
    ),
  );
  const activeHostFirmware = computed(() => {
    return hostFirmware.value.find(
      (firmware: { version: string }) =>
        firmware.version === hostActiveFirmwareId.value,
    );
  });
  const activeCpldFirmware = computed(() => {
    return cpldFirmware.value.find(
      (firmware: { version: string }) =>
        firmware.version === cpldActiveFirmwareId.value,
    );
  });
  const activeHostPbfFirmware = computed(() => {
    return hostFirmware.value.find(
      (firmware: { pbfVersion: string }) =>
        firmware.pbfVersion === hostPbfActiveFirmwareId.value,
    )?.pbfVersion;
  });
  const backupBmcFirmware = computed(() => {
    return bmcFirmware.value.find(
      (firmware: { id: any }) => firmware.id !== bmcActiveFirmwareId.value,
    );
  });
  const backupHostFirmware = computed(() => {
    return hostFirmware.value.find(
      (firmware: { id: any }) => firmware.id !== hostActiveFirmwareId.value,
    );
  });
  const backupCpldtFirmware = computed(() => {
    return cpldFirmware.value.find(
      (firmware: { id: any }) => firmware.id !== cpldActiveFirmwareId.value,
    );
  });

  const setBmcFirmware = (firmware: any) => {
    bmcFirmware.value = firmware;
    bmcActiveFirmwareId.value = firmware[0]?.version;
  };
  const setHostFirmware = (firmware: any) => {
    hostActiveFirmwareId.value = firmware[0]?.version;
    hostFirmware.value = firmware;
  };
  const setCpldFirmware = (firmware: any) => {
    cpldActiveFirmwareId.value = firmware[0]?.version;
    cpldFirmware.value = firmware;
  };
  const setApplyTime = (Time: any) => (applyTime.value = Time);
  const setTftpUploadAvailable = (available: any) =>
    (tftpAvailable.value = available);
  const setUpdateProgress = (updateProgress: any) =>
    (updateProgress.value = updateProgress);
  const setHostPbfVersion = (firmware: any) =>
    (hostPbfActiveFirmwareId.value = firmware[0]?.pbfVersion);

  const getFirmwareInformation = async () => {
    await getFirmwareInventory();
  };
  const getFirmwareInventory = async () => {
    const inventoryList = await api
      .get('/redfish/v1/UpdateService/FirmwareInventory')
      .then(({ data: { Members = [] } = {} }) =>
        Members.map((item: { [x: string]: string }) =>
          api.get(item['@odata.id']),
        ),
      )
      .catch((error) => console.log(error));
    await api
      .all(inventoryList)
      .then((response) => {
        const bmcFirmware: {
          version: any;
          id: any;
          location: any;
          status: any;
        }[] = [];
        const hostFirmware: {
          version: any;
          id: any;
          location: any;
          status: any;
          pbfVersion: any;
        }[] = [];
        const cpldFirmware: {
          version: any;
          id: any;
          location: any;
          status: any;
        }[] = [];
        response.forEach(({ data }: any) => {
          const firmwareType = data?.RelatedItem?.[0]?.['@odata.id']
            .split('/')
            .pop();
          const item = {
            version: data?.Version,
            id: data?.Id,
            location: data?.['@odata.id'],
            status: data?.Status?.Health,
            pbfVersion: data?.Oem?.PBFVersion,
          };
          if (firmwareType === 'bmc') {
            bmcFirmware.push(item);
          } else if (
            data['@odata.id'] ===
            '/redfish/v1/UpdateService/FirmwareInventory/bios_active'
          ) {
            hostFirmware.push(item);
          } else if (
            data['@odata.id'] ===
            '/redfish/v1/UpdateService/FirmwareInventory/cpld_active'
          ) {
            cpldFirmware.push(item);
          }
        });
        setBmcFirmware(bmcFirmware);
        setHostFirmware(hostFirmware);
        setCpldFirmware(cpldFirmware);
        setHostPbfVersion(hostFirmware);
      })
      .catch((error) => {
        console.log(error);
      });
  };
  const getUpdateServiceSettings = () => {
    api
      .get('/redfish/v1/UpdateService')
      .then(({ data }) => {
        const applyTime =
          data.HttpPushUriOptions.HttpPushUriApplyTime.ApplyTime;
        const allowableActions =
          data?.Actions?.['#UpdateService.SimpleUpdate']?.[
            'TransferProtocol@Redfish.AllowableValues'
          ];
        setApplyTime(applyTime);
        if (allowableActions?.includes('TFTP')) {
          setTftpUploadAvailable(true);
        }
      })
      .catch((error) => console.log(error));
  };
  const setApplyTimeOnReset = () => {
    const data = {
      HttpPushUriOptions: {
        HttpPushUriApplyTime: {
          ApplyTime: 'OnReset',
        },
      },
    };
    return api
      .patch('/redfish/v1/UpdateService', data)
      .then(() => setApplyTime('OnReset'))
      .catch((error) => console.log(error));
  };
  const uploadFirmware = async (image: any) => {
    if (applyTime.value !== 'OnReset') {
      // ApplyTime must be set to OnReset before making
      // request to update firmware
      await setApplyTimeOnReset();
    }
    return await api
      .post('/redfish/v1/UpdateService', image, {
        headers: { 'Content-Type': 'application/octet-stream' },
      })
      .then(async ({ data }) => {
        const { Type: type, '@odata.id': taskUrl } = data;
        return {
          type,
          taskUrl,
        };
      })
      .catch(() => {
        throw new Error(t('pageFirmware.toast.errorUpdateFirmware') as string);
      });
  };
  const uploadFirmwareTFTP = async (fileAddress: any) => {
    const data = {
      TransferProtocol: 'TFTP',
      ImageURI: fileAddress,
    };
    if (applyTime.value !== 'OnReset') {
      // ApplyTime must be set to OnReset before making
      // request to update firmware
      await setApplyTimeOnReset();
    }
    return await api
      .post(
        '/redfish/v1/UpdateService/Actions/UpdateService.SimpleUpdate',
        data,
        undefined,
      )
      .then(async ({ data }) => {
        const { Type: type, '@odata.id': taskUrl } = data;
        return {
          type,
          taskUrl,
        };
      })
      .catch((error) => {
        console.log(error);
        throw new Error(t('pageFirmware.toast.errorUpdateFirmware') as string);
      });
  };
  const switchBmcFirmwareAndReboot = async () => {
    const backupLocation = backupBmcFirmware.value.location;
    const data = {
      Links: {
        ActiveSoftwareImage: {
          '@odata.id': backupLocation,
        },
      },
    };
    return await api.patch('/redfish/v1/Managers/bmc', data).catch((error) => {
      console.log(error);
      throw new Error(t('pageFirmware.toast.errorSwitchImages') as string);
    });
  };
  const getUpdateinfo = async (taskUrl: string) => {
    return await api
      .get(taskUrl)
      .then(({ data }) => {
        setUpdateProgress(data.PercentComplete);
        return { TaskState: data.TaskState, TaskStatus: data.TaskStatus };
      })
      .catch(() => {
        throw 'page not found!';
      });
  };
  const getFirmwareInfo = async (id: string) => {
    return await api
      .get('/redfish/v1/UpdateService/FirmwareInventory/' + id)
      .then(({ data }) => {
        return data;
      });
  };
  const deleteBrokenFirmware = async (id: string) => {
    const data = JSON.stringify({ data: [] });
    await api.post(
      '/xyz/openbmc_project/software/' + id + '/action/Delete',
      data,
      undefined,
    );
  };

  return {
    bmcFirmware,
    hostFirmware,
    cpldFirmware,
    hostPbfActiveFirmwareId,
    bmcActiveFirmwareId,
    hostActiveFirmwareId,
    cpldActiveFirmwareId,
    applyTime,
    tftpAvailable,
    updateProgress,
    isTftpUploadAvailable,
    isSingleFileUploadEnabled,
    activeBmcFirmware,
    activeHostFirmware,
    activeCpldFirmware,
    activeHostPbfFirmware,
    backupBmcFirmware,
    backupHostFirmware,
    backupCpldtFirmware,
    setBmcFirmware,
    setHostFirmware,
    setCpldFirmware,
    setApplyTime,
    setTftpUploadAvailable,
    setUpdateProgress,
    setHostPbfVersion,
    getFirmwareInformation,
    getFirmwareInventory,
    getUpdateServiceSettings,
    setApplyTimeOnReset,
    uploadFirmware,
    uploadFirmwareTFTP,
    switchBmcFirmwareAndReboot,
    getUpdateinfo,
    getFirmwareInfo,
    deleteBrokenFirmware,
  };
});
